<!DOCTYPE html>
<html>
<head>
<title>Static Force Analysis Diagram</title>
<style>
  body {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    margin: 0;
    background-color: #f0f0f0;
  }
  canvas {
    border: 1px solid #999;
    background-color: #fff;
  }
</style>
</head>
<body>
<canvas id="canvas" width="600" height="500"></canvas>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

// Style settings
ctx.strokeStyle = 'black';
ctx.fillStyle = 'black';
ctx.lineWidth = 2;

// Helper function to draw an arrow with a line-art head
function drawArrow(ctx, fromx, fromy, tox, toy, headlen) {
    const angle = Math.atan2(toy - fromy, tox - fromx);
    ctx.beginPath();
    ctx.moveTo(fromx, fromy);
    ctx.lineTo(tox, toy);
    ctx.stroke(); // Draw the shaft of the arrow
    
    // Draw the arrowhead
    ctx.beginPath();
    ctx.moveTo(tox, toy);
    ctx.lineTo(tox - headlen * Math.cos(angle - Math.PI / 6), toy - headlen * Math.sin(angle - Math.PI / 6));
    ctx.moveTo(tox, toy);
    ctx.lineTo(tox - headlen * Math.cos(angle + Math.PI / 6), toy - headlen * Math.sin(angle + Math.PI / 6));
    ctx.stroke();
}

// Parameters
const cx = 300;
const cy = 250;
const radius = 80;
const ropeLengthAB = 180;
const ropeLengthCD = 160;

// Angles in degrees. Standard mathematical convention (CCW from positive x-axis).
const angle_AB_deg = 45;
const angle_inter = 150;
const angle_CD_deg = angle_AB_deg + angle_inter; // 195 degrees

// Convert to radians for canvas. Canvas y-axis is inverted, so use negative angles for standard trig functions.
const angle_AB_rad = -angle_AB_deg * Math.PI / 180;
const angle_CD_rad = -angle_CD_deg * Math.PI / 180;

// 1. Draw the sphere
ctx.beginPath();
ctx.arc(cx, cy, radius, 0, 2 * Math.PI);
ctx.stroke();

// 2. Draw rope AB and support B
const Ax = cx + radius * Math.cos(angle_AB_rad);
const Ay = cy + radius * Math.sin(angle_AB_rad);
const Bx = cx + ropeLengthAB * Math.cos(angle_AB_rad);
const By = cy + ropeLengthAB * Math.sin(angle_AB_rad);

ctx.beginPath();
ctx.moveTo(Ax, Ay);
ctx.lineTo(Bx, By);
ctx.stroke();

// Support at B
const supportLenB = 50;
const angleSupportB = angle_AB_rad + Math.PI / 2; // Perpendicular to the rope
const B1x = Bx + supportLenB / 2 * Math.cos(angleSupportB);
const B1y = By + supportLenB / 2 * Math.sin(angleSupportB);
const B2x = Bx - supportLenB / 2 * Math.cos(angleSupportB);
const B2y = By - supportLenB / 2 * Math.sin(angleSupportB);

ctx.beginPath();
ctx.moveTo(B1x, B1y);
ctx.lineTo(B2x, B2y);
ctx.stroke();

// Hatching for support B
const hatchLen = 12;
const hatchCountB = 7;
const hatchSpacingB = supportLenB / (hatchCountB - 1);
const vecSupportB_x = Math.cos(angleSupportB);
const vecSupportB_y = Math.sin(angleSupportB);
const angleHatchB = angle_AB_rad + Math.PI; // Parallel to rope, pointing away
for (let i = 0; i < hatchCountB; i++) {
    const startX = B2x + i * hatchSpacingB * vecSupportB_x;
    const startY = B2y + i * hatchSpacingB * vecSupportB_y;
    const endX = startX + hatchLen * Math.cos(angleHatchB);
    const endY = startY + hatchLen * Math.sin(angleHatchB);
    ctx.beginPath();
    ctx.moveTo(startX, startY);
    ctx.lineTo(endX, endY);
    ctx.stroke();
}

// 3. Draw rope CD and support C
const Dx = cx + radius * Math.cos(angle_CD_rad);
const Dy = cy + radius * Math.sin(angle_CD_rad);
const Cx = cx + ropeLengthCD * Math.cos(angle_CD_rad);
const Cy = cy + ropeLengthCD * Math.sin(angle_CD_rad);

ctx.beginPath();
ctx.moveTo(Dx, Dy);
ctx.lineTo(Cx, Cy);
ctx.stroke();

// Support at C
const supportLenC = 50;
ctx.beginPath();
ctx.moveTo(Cx, Cy - supportLenC / 2);
ctx.lineTo(Cx, Cy + supportLenC / 2);
ctx.stroke();

// Hatching for support C
const hatchCountC = 7;
const hatchSpacingC = supportLenC / (hatchCountC - 1);
for (let i = 0; i < hatchCountC; i++) {
    const y = (Cy - supportLenC / 2) + i * hatchSpacingC;
    ctx.beginPath();
    ctx.moveTo(Cx, y);
    ctx.lineTo(Cx - hatchLen, y);
    ctx.stroke();
}

// 4. Draw internal elements: dashed lines, angle arcs, and force vectors
// Dashed lines from center to circumference
ctx.beginPath();
ctx.setLineDash([4, 4]);
ctx.moveTo(cx, cy);
ctx.lineTo(Ax, Ay);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(cx, cy);
ctx.lineTo(Dx, Dy);
ctx.stroke();
ctx.setLineDash([]);

// 150 deg angle arc
const arcRadius150 = 45;
ctx.beginPath();
ctx.arc(cx, cy, arcRadius150, angle_CD_rad, angle_AB_rad, false);
ctx.stroke();

// Force vectors from center O
const arrowLen = 40;
const arrowHeadLen = 15;
const tempLineWidth = ctx.lineWidth;
ctx.lineWidth = 2.5;
drawArrow(ctx, cx, cy, cx + arrowLen * Math.cos(angle_AB_rad), cy + arrowLen * Math.sin(angle_AB_rad), arrowHeadLen);
drawArrow(ctx, cx, cy, cx + arrowLen * Math.cos(angle_CD_rad), cy + arrowLen * Math.sin(angle_CD_rad), arrowHeadLen);
ctx.lineWidth = tempLineWidth;

// 5. Draw 45 deg angle mark, styled like the original
const angleMarkTipX = cx - 105;
const angleMarkTipY = cy + 90;
const standHeight = 20;
const standHalfWidth = 25;

const standBaseY = angleMarkTipY + standHeight;
const standBaseLeftX = angleMarkTipX - standHalfWidth;
const standBaseRightX = angleMarkTipX + standHalfWidth;

// The "stand" structure
ctx.beginPath();
ctx.moveTo(standBaseLeftX, standBaseY);
ctx.lineTo(standBaseRightX, standBaseY);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(standBaseLeftX, standBaseY);
ctx.lineTo(angleMarkTipX, angleMarkTipY);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(standBaseRightX, standBaseY);
ctx.lineTo(angleMarkTipX, angleMarkTipY);
ctx.stroke();

// Dashed lines for the angle from the stand's tip
const dashedLineLen45 = 80;
ctx.beginPath();
ctx.setLineDash([4, 4]);
// Dashed line parallel to AB
const endParallelX = angleMarkTipX + dashedLineLen45 * Math.cos(angle_AB_rad);
const endParallelY = angleMarkTipY + dashedLineLen45 * Math.sin(angle_AB_rad);
ctx.moveTo(angleMarkTipX, angleMarkTipY);
ctx.lineTo(endParallelX, endParallelY);
ctx.stroke();
// Dashed horizontal line
ctx.beginPath();
ctx.moveTo(angleMarkTipX, angleMarkTipY);
ctx.lineTo(angleMarkTipX - dashedLineLen45, angleMarkTipY);
ctx.stroke();
ctx.setLineDash([]);

// Arc for 45 deg
const arcRadius45 = 25;
ctx.beginPath();
// Angle between horizontal (PI rad) and the AB line (angle_AB_rad).
ctx.arc(angleMarkTipX, angleMarkTipY, arcRadius45, angle_AB_rad, Math.PI, true);
ctx.stroke();

// 6. Add labels
ctx.font = 'italic bold 20px Times New Roman';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';

ctx.fillText('O', cx + 12, cy + 12);
ctx.fillText('A', Ax + 15, Ay - 10);
ctx.fillText('B', Bx + 20, By - 20);
ctx.fillText('D', Dx - 15, Dy + 10);
ctx.fillText('C', Cx - 20, Cy);

ctx.font = '20px Times New Roman';
ctx.fillText('150°', cx - 15, cy - 10);
ctx.fillText('45°', angleMarkTipX - 35, angleMarkTipY - 15);

</script>
</body>
</html>